﻿using System;
using System.Windows.Forms;

namespace ReagentStore.UTL
{
	public abstract class ValidatorBase
	{
		protected ValidatorBase(Control control, string errortext)
		{
			Control = control;
			ErrorText = errortext;
		}

		protected ValidatorBase()
		{
			throw new NotImplementedException();
		}

		public Control Control { get; private set; }
		public string ErrorText { get; private set; }
		public abstract bool IsValid();
	}

	public abstract class RangeValidator<T> : ValidatorBase
		where T : IComparable
	{
		protected RangeValidator(Control control, string errortext)
			: base(control, errortext)
		{
		}

		public abstract T Min { get; set; }
		public abstract T Max { get; set; }
	}

	public class DecimalRangeValidator : RangeValidator<decimal>
	{
		private decimal _max;
		private decimal _min;

		#region Overrides of RangeValidator<int>

		public override decimal Min
		{
			get { return _min; }
			set
			{
				if (value <= _max)
					_min = value;
			}
		}

		public override decimal Max
		{
			get { return _max; }
			set
			{
				if (value >= _min)
					_max = value;
			}
		}

		#endregion

		public DecimalRangeValidator(Control control, string errortext, decimal min, decimal max)
			: base(control, errortext)
		{
			if (min > max)
				throw new ArgumentException("max must be bigger than min.");

			_min = min;
			_max = max;
		}

		#region Overrides of ValidatorBase

		public override bool IsValid()
		{
			bool result = true;

			switch (Control.GetType().Name)
			{
				case "NumericUpDown":
					decimal ud = ((NumericUpDown) Control).Value;
					if ((ud < Min) || (ud > Max))
						result = false;
					break;

				case "TrackBar":
					var tb = (decimal) ((TrackBar) Control).Value;
					if ((tb < Min) || (tb > Max))
						result = false;
					break;
			}

			return result;
		}

		#endregion
	}

	public class DateTimeRangeValidator : RangeValidator<DateTime>
	{
		private DateTime _max;
		private DateTime _min;

		#region Overrides of RangeValidator<T>

		public override DateTime Min
		{
			get { return _min; }
			set
			{
				if (value <= _max)
					_min = value;
			}
		}

		public override DateTime Max
		{
			get { return _max; }
			set
			{
				if (value >= _min)
					_max = value;
			}
		}

		#endregion

		public DateTimeRangeValidator(Control control, string errortext, DateTime min, DateTime max)
			: base(control, errortext)
		{
			if (min > max)
				throw new ArgumentException("max must be bigger than min.");

			_min = min;
			_max = max;
		}

		#region Overrides of ValidatorBase

		public override bool IsValid()
		{
			bool result = true;

			switch (Control.GetType().Name)
			{
				case "DateTimePicker":
					DateTime dp = ((DateTimePicker) Control).Value;
					if ((dp < Min) || (dp > Max))
						result = false;
					break;

				case "MaskedTextBox":
					var mb = (MaskedTextBox) Control;
					if (mb.ValidatingType.Equals(typeof (DateTime)))
					{
						DateTime dmb = DateTime.Parse(mb.Text);
						if ((dmb < Min) || (dmb > Max))
							result = false;
					}
					break;
			}

			return result;
		}

		#endregion
	}


	public class RequiredValidator : ValidatorBase
	{
		public RequiredValidator(Control control, string errortext)
			: base(control, errortext)
		{
		}

		#region Implementation of ValidatorBase

		public override bool IsValid()
		{
			bool result = true;
			switch (Control.GetType().Name)
			{
				case "TextBox":
					result = !string.IsNullOrEmpty(Control.Text.Trim());
					break;

				case "ComboBox":
					var cb = (ComboBox) Control;
					if (cb.DropDownStyle != ComboBoxStyle.DropDownList)
						result = !string.IsNullOrEmpty(cb.Text);
					else
						result = ((ComboBox) Control).SelectedIndex >= 0;
					break;

				case "ListView":
					var lv = (ListView) Control;
					result = lv.SelectedItems.Count > 0;
					break;

				case "ListBox":
					var lb = (ListBox) Control;
					result = lb.SelectedIndex >= 0;
					break;
			}

			return result;
		}

		#endregion
	}
}